﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * 目标标本：4.0.30319.239
 * 
 * 最后修改：2011/11/11 17:02:30
 * ************************************************************/
namespace Mozlite.Common
{
    using System;
    using System.Linq;
    using System.Text;
    using System.Collections.Generic;
    using Mozlite.Common.Configuration;

    /// <summary>
    /// 权限管理类。
    /// </summary>
    public class Permissions
    {
        /// <summary>
        /// 初始化类<see cref="T:Mozlite.Common.Permissions"/>。
        /// </summary>
        private Permissions() { }

        static Permissions()
        {
            dllPermissions = CommonHelper.FindType<PermissionBase>();
        }

        private static List<PermissionBase> dllPermissions = new List<PermissionBase>();

        private static string GetAllSchemasCacheKey()
        {
            return string.Format("Mozlite.Common.Permissions.{0}", SiteSettings.Current.SettingsID);
        }

        private static string GetSchemaCacheKey<T>()
        {
            return string.Format("SettingsID.{1}::PermissionSchemas-{0}", typeof(T).FullName, SiteSettings.Current.SettingsID);
        }

        private static string GetPermissionCacheKey<T>()
        {
            return string.Format("SettingsID.{1}::Permissions-{0}", typeof(T).FullName, SiteSettings.Current.SettingsID);
        }

        /// <summary>
        /// 获取DLL文件中所有权限类。
        /// </summary>
        /// <returns>返回DLL文件中所有权限类列表。</returns>
        public static List<PermissionBase> LoadDllPermissions()
        {
            return dllPermissions;
        }

        /// <summary>
        /// 移除缓存。
        /// </summary>
        /// <typeparam name="T">移除缓存类型。</typeparam>
        public static void RemoveCache<T>()
        {
            Caches.Remove(GetSchemaCacheKey<T>());
            Caches.Remove(GetPermissionCacheKey<T>());
        }

        /// <summary>
        /// 拷贝权限方案。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="targetSchemeID">权限方案ID。</param>
        /// <param name="permissionSchema">权限方案。</param>
        /// <returns>如果拷贝成功返回<c>true</c>，否则返回<c>false</c>。</returns>
        public static bool CopyPermissionSchema<T>(Guid targetSchemeID, PermissionSchema permissionSchema) where T:PermissionBase
        {
            if (string.IsNullOrEmpty(permissionSchema.SchemaName))
            {
                return false;
            }
            if (string.IsNullOrEmpty(permissionSchema.Description))
            {
                return false;
            }
            bool flag = SecurityDataProvider.Current.CopyPermissionSchema(SiteSettings.Current.SettingsID, targetSchemeID, permissionSchema.SchemaName, permissionSchema.Description);
            if (flag)
            {
                RemoveCache<T>();
            }
            return flag;
        }
       
        /// <summary>
        /// 创建权限方案。
        /// </summary>
        /// <param name="permissionSchema">权限方案。</param>
        /// <returns>如果创建成功返回<c>true</c>，否则返回<c>false</c>。</returns>
        public static bool CreatePermissionSchema(PermissionSchema permissionSchema)
        {
            if (SecurityDataProvider.Current.CreatePermissionSchema(permissionSchema))
            {
                Caches.Remove(GetAllSchemasCacheKey());
                return true;
            }
            return false;
        }
       
        /// <summary>
        /// 删除权限方案。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemeID">权限方案ID。</param>
        /// <returns>如果删除成功返回<c>true</c>，否则返回<c>false</c>。</returns>
        public static bool DeletePermissionSchema<T>(Guid schemeID) where T : PermissionBase
        {
            if (SecurityDataProvider.Current.DeletePermissionSchema(SiteSettings.Current.SettingsID, schemeID))
            {
                RemoveCache<T>();
                return true;
            }
            return false;
        }

        private static Dictionary<Guid, Dictionary<int, T>> LoadPermissionsByType<T>() where T : PermissionBase, new()
        {
            return Caches.Get<Dictionary<Guid, Dictionary<int, T>>>(GetPermissionCacheKey<T>(), Globals.MinuteSeconds * 3, Globals.MinuteSeconds * 3, () =>
            {
                var permissions = SecurityDataProvider.Current.GetAllPermissions<T>(SiteSettings.Current.SettingsID);
                if (permissions.Count == 0)
                {
                    CreatePermissionSchema(GetSingleSchema<T>());
                }
                return permissions;
            });
        }

        /// <summary>
        /// 获取单个权限方案的用户权限。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <returns>返回当前用户的权限实例对象。</returns>
        public static T GetPermission<T>() where T : PermissionBase, new()
        {
            return Permissions.GetPermission<T>(Guid.Empty);
        }

        /// <summary>
        /// 获取单个权限方案的用户权限。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemaID">权限方案ID。</param>
        /// <returns>返回当前用户的权限实例对象。</returns>
        public static T GetPermission<T>(Guid schemaID) where T : PermissionBase, new()
        {
            if (schemaID == Guid.Empty)
                schemaID = new T().SchemaID;
            return Permissions.GetPermission<T>(schemaID, AppContext.Current.User.RoleIDs);
        }

        /// <summary>
        /// 获取用户组中的权限集合的叠加权限。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemaID">权限方案ID。</param>
        /// <param name="roleIDs">用户组ID列表。</param>
        /// <returns>返回用户组中的权限集合的叠加权限。</returns>
        public static T GetPermission<T>(Guid schemaID, List<int> roleIDs) where T : PermissionBase, new()
        {
            roleIDs.Sort();
            string key = string.Format("SchemaID::{0}::RoleIDs::{1}::SettingsID::{2}", schemaID, roleIDs.Join(), SiteSettings.Current.SettingsID);
            return Caches.Get<T>(key, () =>
            {
                T permission = new T();
                foreach (int roleID in roleIDs)
                {
                    T p = GetPermission<T>(schemaID, roleID);
                    if (p != null)
                    {
                        permission.Merger(p);
                    }
                }
                Caches.Max(key, permission, new System.Web.Caching.CacheDependency(null, new string[] { GetPermissionCacheKey<T>(), GetSchemaCacheKey<T>() }));
                return permission;
            });
        }
       
        /// <summary>
        /// 获取角色的权限。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemeID">权限ID。</param>
        /// <param name="roleID">角色ID。</param>
        /// <returns>返回角色的权限。</returns>
        public static T GetPermission<T>(Guid schemeID, int roleID) where T : PermissionBase, new()
        {
            T permission;
            if (LoadPermissions<T>(schemeID).TryGetValue(roleID, out permission))
                return permission;
            return null;
        }
      
        /// <summary>
        /// 获取用户组中的权限集合的叠加权限。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemaID">权限方案ID。</param>
        /// <param name="roleIDs">用户组ID集合。</param>
        /// <returns>返回用户组中的权限集合的叠加权限。</returns>
        public static T GetPermission<T>(Guid schemaID, string roleIDs) where T : PermissionBase, new()
        {
            return GetPermission<T>(schemaID, roleIDs.Split<int>());
        }

        /// <summary>
        /// 加载权限方案中的集合列表(角色ID为键)。
        /// </summary>
        /// <typeparam name="T">权限名称。</typeparam>
        /// <returns>返回权限方案中的集合列表。</returns>
        public static Dictionary<int, T> LoadPermissions<T>() where T : PermissionBase, new()
        {
            return LoadPermissions<T>(Guid.Empty);
        }
      
        /// <summary>
        /// 加载权限方案中的集合列表(角色ID为键)。
        /// </summary>
        /// <typeparam name="T">权限名称。</typeparam>
        /// <param name="schemeID">权限方案ID。</param>
        /// <returns>返回权限方案中的集合列表。</returns>
        public static Dictionary<int, T> LoadPermissions<T>(Guid schemeID) where T : PermissionBase, new()
        {
            if (schemeID == Guid.Empty)
                schemeID = new T().SchemaID;
            Dictionary<int, T> dictionary;
            var permissions = LoadPermissionsByType<T>();
            if (permissions == null)
                dictionary = new Dictionary<int, T>();
            else if (!permissions.TryGetValue(schemeID, out dictionary))
            {
                if (permissions.Count == 1)
                    dictionary = permissions.Values.First<Dictionary<int, T>>();
                else
                    dictionary = new Dictionary<int, T>();
            }
            foreach (Role role in Roles.LoadRoles().Values)
            {
                if (!dictionary.ContainsKey(role.RoleID))
                {
                    T t = new T();
                    t.RoleID = role.RoleID;
                    t.SchemaID = schemeID;

                    dictionary.Add(role.RoleID, t);
                }
            }
            return dictionary;
        }
       
        /// <summary>
        /// 获取权限方案。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemeID">权限方案ID。</param>
        /// <returns>返回权限方案。</returns>
        public static PermissionSchema GetPermissionSchema<T>(Guid schemeID) where T : PermissionBase, new()
        {
            PermissionSchema schema;
            if (LoadPermissionSchemas<T>().TryGetValue(schemeID, out schema))
            {
                return schema;
            }
            return null;
        }
       
        /// <summary>
        /// 获取权限方案。
        /// </summary>
        /// <param name="schemaID">方案ID。</param>
        /// <returns>返回权限方案实例对象。</returns>
        public static PermissionSchema GetPermissionSchema(Guid schemaID)
        {
            return SecurityDataProvider.Current.GetPermissionSchema(SiteSettings.Current.SettingsID, schemaID);
        }

        /// <summary>
        /// 加载所有权限方案列表。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <returns>返回所有权限方案列表。</returns>
        public static Dictionary<Guid, PermissionSchema> LoadPermissionSchemas<T>()
        {
            return Caches.Get<Dictionary<Guid, PermissionSchema>>(GetSchemaCacheKey<T>(), () =>
            {
                Dictionary<Guid, PermissionSchema> schemas = SecurityDataProvider.Current.GetAllPermissionSchemas(SiteSettings.Current.SettingsID, typeof(T).GetInstanceType());
                if (schemas != null && schemas.Count > 0)
                    Caches.Max(GetSchemaCacheKey<T>(), schemas, new System.Web.Caching.CacheDependency(null, new string[] { GetAllSchemasCacheKey() }));
                return schemas;
            });
        }

        /// <summary>
        /// 保存权限列表。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="permissions">权限列表。</param>
        /// <returns>如果保存成功返回<c>true</c>，否则返回<c>false</c>。</returns>
        public static bool SavePermissions<T>(List<T> permissions) where T : PermissionBase, new()
        {
            if (SecurityDataProvider.Current.SavePermissions(permissions.ConvertAll<PermissionBase>(i => { return i; })))
            {
                RemoveCache<T>();
                return true;
            }
            return false;
        }
        
        /// <summary>
        /// 更新权限方案。
        /// </summary>
        /// <param name="permissionSchema">权限方案对象实例。</param>
        /// <returns>如果保存成功返回<c>true</c>，否则返回<c>false</c>。</returns>
        public static bool UpdatePermissionSchema(PermissionSchema permissionSchema)
        {
            if (SecurityDataProvider.Current.UpdatePermissionSchema(permissionSchema))
            {
                Caches.Remove(GetAllSchemasCacheKey());
                return true;
            }
            return false;
        }
       
        /// <summary>
        /// 加载所有权限方案列表。
        /// </summary>
        /// <returns>返回所有权限方案列表。</returns>
        public static Dictionary<Guid, PermissionSchema> LoadPermissionSchemas()
        {
            return Caches.Get<Dictionary<Guid, PermissionSchema>>(GetAllSchemasCacheKey(), Globals.MinuteSeconds * 3, Globals.MinuteSeconds * 3, () =>
            {
                return SecurityDataProvider.Current.LoadPermissionSchemas(SiteSettings.Current.SettingsID);
            });
        }

        private static PermissionSchema GetSingleSchema<T>() where T : PermissionBase, new()
        {
            T instance = new T();
            return new PermissionSchema { SchemaID = instance.SchemaID, SettingsID = instance.SettingsID, SchemaName = Resources.GetString("Schema." + typeof(T).Name, null, Routes.ControlPanel), PermissionType = typeof(T).GetInstanceType(), LastModified = DateTime.Now };
        }

        /// <summary>
        /// 判断权限方案名称是否重复。
        /// </summary>
        /// <typeparam name="T">权限类型。</typeparam>
        /// <param name="schemaName">权限方案名称。</param>
        /// <param name="schemaID">权限方案ID。</param>
        /// <returns>返回判断结果。</returns>
        public static bool IsPermissionSchemaNameValid<T>(string schemaName, Guid schemaID) where T : PermissionBase, new()
        {
            var schemas = LoadPermissionSchemas<T>();
            if (schemas.Count == 0)
                return true;
            foreach (var schema in schemas.Values)
            {
                if (schema.SchemaName.IsMatched(schemaName))
                {
                    if(schemaID == Guid.Empty || schemaID != schema.SchemaID)
                        return false;
                }
            }
            return true;
        }
    }
}